import * as DataProcess from './dataProcessEx';

const defaultFields = {
  U: 'U',
  V: 'V',
  W: 'W',
  H: 'H',
  lon: 'lon',
  lat: 'lat',
  lev: 'lev'
};

const defaultColorTable = [[[1.0, 1.0, 1.0]]];

/**
 * 给一个笛卡尔点和一个方向,一个距离,计算另一个笛卡尔点
 * @param {*} ptCartesian
 * @param {*} vecCartesian
 * @param {*} distance
 */
function calDistanceCartesian3(cart1, vecCartesian, distance) {
  let enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(cart1);
  const normal = new Cesium.Cartesian3();
  Cesium.Cartesian3.normalize(vecCartesian, normal);
  const move = new Cesium.Cartesian3();
  Cesium.Cartesian3.multiplyByScalar(normal, distance, move);

  let cart2 = new Cesium.Cartesian3();
  Cesium.Matrix4.multiplyByPoint(enuMatrix, move, cart2);
  return cart2;
}

/**
 * 计算两个经纬度之间的距离
 * @param {*} ptLonlat1
 * @param {*} ptLonlat2
 */
export function calLonlatDistance(ptLonlat1, ptLonlat2) {
  const cart1 = Cesium.Cartographic.fromDegrees(ptLonlat1.x, ptLonlat1.y, ptLonlat1.z);
  const cart2 = Cesium.Cartographic.fromDegrees(ptLonlat2.x, ptLonlat2.y, ptLonlat2.z);
  const geodesic = new Cesium.EllipsoidGeodesic(cart1, cart2);
  const dist = geodesic.surfaceDistance;
  return dist;
}

const defaultParticleSystemOptions = {
  // 粒子个数
  maxParticles: 64 * 64,

  // 抬升高度
  particleHeight: 0.0,

  // 线宽
  lineWidth: 1.0,

  // 线长倍数
  lineLengthFactor: 3
};

export class lineWindy {
  constructor(
    viewer,
    {
      input,
      type = 'nc',
      fields,
      valueRange = { min: -100, max: 100 },
      offset = { lon: 0, lat: 0, lev: 0 },
      userInput = defaultParticleSystemOptions,
      colorTable = defaultColorTable,
      colour = 'speed'
    }
  ) {
    this.viewer = viewer;
    this.entities = [];

    this.userInput = userInput;
    this.input = input;
    this.colour = colour;
    this.type = type;
    this.fields = {
      ...defaultFields,
      ...fields
    };
    this.offset = offset;
    this.valueRange = valueRange;
    this.colorTable = colorTable;

    // 可以外加一个包围盒,只显示包围盒内的实体
    this.AABBox = undefined;

    // 可以加一个切面, 只显示切面上的
    this.Section = undefined;
  }

  async init() {
    try {
      let data = await DataProcess.loadData(this.input, this.type, {
        fields: this.fields,
        valueRange: this.valueRange,
        offset: this.offset,
        colorTable: this.colorTable
      });
      this.data = data;
      this._addPrimitives();
      return data;
    } catch (e) {
      throw e;
    }
  }

  setUserInput(param) {
    Object.assign(this.userInput, param);
  }

  /**
   * 设置包围盒
   * @param {*} minLon
   * @param {*} minLat
   * @param {*} minH
   * @param {*} maxLon
   * @param {*} maxLat
   * @param {*} maxH
   */
  setAABBox(minLon, minLat, minH, maxLon, maxLat, maxH) {
    this.AABBox = { minLon, minLat, minH, maxLon, maxLat, maxH };
  }

  /**
   * 设置切面
   * @param {String} type 类型,选择"x"|"y"|"z"
   * @param {Number} value 值,0到1之间
   */
  setSection(type, value) {
    this.Section = { type, value };
  }

  /**
   * 刷新数据
   */
  fresh() {
    this.remove();
    this._addPrimitives();
  }

  _addPrimitives() {
    let material1 = new zz3d.LineFlowMaterial({
      //动画线材质
      color: Cesium.Color.CHARTREUSE,
      duration: Cesium.Math.randomBetween(500, 1000), //时长，控制速度
      url: '/img/textures/lineClr.png',
      bgUrl: '/img/textures/colortable.png',
      repeat: new Cesium.Cartesian2(1, 1)
    });

    let infos = undefined;
    if (this.Section) {
      infos = DataProcess.randomizeParticlesSection(this.userInput.maxParticles, this.data, this.Section);
    } else {
      infos = DataProcess.randomizeParticles(
        this.userInput.maxParticles,
        this.data,
        this.AABBox,
        this.userInput.particleHeight
      );
    }

    for (let i = 0; i < infos.length; ++i) {
      const info = infos[i];

      let v = new Cesium.Cartesian3(info.U, info.V, info.W);
      let d = Cesium.Cartesian3.magnitude(v);

      const pt1 = Cesium.Cartesian3.fromDegrees(info.lon, info.lat, this.userInput.particleHeight + info.H);
      const pt2 = calDistanceCartesian3(pt1, v, d * this.userInput.lineLengthFactor);

      // 把速度修改到0和1之间
      d = d / 6;
      if (d > 1.0) d = 1.0;

      // 生成随机初始位置,否则看着太有规律
      let pos = Math.random();

      let ent = this.viewer.entities.add({
        polyline: {
          positions: [pt1, pt2],
          // colors的第一个分量是颜色，第二个分量是随机位置
          colors: [new Cesium.Color(d, pos, 1.0, 1.0), new Cesium.Color(d, pos, 1.0, 1.0)],
          width: this.userInput.lineWidth,
          material: material1,
          show: true
        }
      });
      this.entities.push(ent);
    }
  }

  show() {
    this.entities.forEach(ent => {
      ent.polyline.show = true;
    });
  }

  hide() {
    this.entities.forEach(ent => {
      ent.polyline.show = false;
    });
  }

  destroy() {
    this.remove();
  }

  remove() {
    this.entities.forEach(ent => {
      this.viewer.entities.remove(ent);
    });
    this.entities.length = 0;
  }

  centerAt() {
    this.viewer.flyTo(this.entities);
  }
}
